################################################################################
# fscheme (C) Copyright funnyos@qq.com 2018
#
# This software is freely distributable under the terms of the MIT 
# License. See the file LICENSE for details.
################################################################################

#memory layout
memory.bs = 0x01000000  #bss segment
memory.cs = 0x02000000  #code segment
memory.ds = 0x03000000  #data/text segment
memory.es = 0x04000000  #evalated value segment
memory.hp = 0x05000000  #heap pointer
memory.sp = 0x06000000  #stack pointer
memory.wp = 0x07000000  #swap pointer

#syscall
print_int    = 01 #$a0  = integer
print_float  = 02 #$f12 = float
print_double = 03 #$f12 = double
print_string = 04 #$a0  = string
read_int     = 05 #returns integer in $v0
read_float   = 06 #returns float   in $f0
read_double  = 07 #returns double  in $f0
read_string  = 08 #$a0 = buffer, $a1 = length
malloc       = 09 #$a0 = size of request returns pointer in $v0
exit         = 10
print_char   = 11 #$a0 = char
read_char    = 12 #returns char (in $v0)
open_file    = 13 #$a0 = filename (string), $a1 =flags, $a2 = mode 0=read 1= wr 2=rw 8=append. returns file descriptor (in $v0)
read_file    = 14 #$a0 = file descriptor, $a1 = buffer, $a2 = length. returns num chars read (in $v0 )
write_file   = 15 #$a0 = file descriptor, $a1 = buffer, $a2 = length. returns num chars written (in $v0 )
close_file   = 16 #$a0 = file descriptor
exit2        = 17 #$a0 = result

################################################################################
# Global data structures
################################################################################
.data

bss:           .space  0x01000000
codeseg:       .space  0x01000000
dataseg:       .space  0x01000000
resultseg:     .space  0x01000000
heap:          .space  0x01000000
stack:         .space  0x01000000
swap:          .space  0x01000000

memory.bs      .space  4  #bss segment
memory.cs      .space  4  #code segment
memory.ds      .space  4  #data/text segment
memory.es      .space  4  #evalated value segment
memory.hp      .space  4  #heap pointer
memory.sp      .space  4  #stack pointer
memory.wp      .space  4  #swap pointer

.align 4

################################################################################
# Special Forms Table
################################################################################
special_forms:
n_eval:       .asciiz "eval"
n_apply:      .asciiz "apply"
n_define:     .asciiz "define"
n_set:        .asciiz "set!"
n_set_car:    .asciiz "set-car!"
n_set_cdr:    .asciiz "set-cdr!"
n_cons:       .asciiz "cons"
n_car:        .asciiz "car"
n_cdr:        .asciiz "cdr"
n_lambda:     .asciiz "lambda"
n_let:        .asciiz "let"
n_let_star:   .asciiz "let*"
n_letrec:     .asciiz "letrec"
n_begin:      .asciiz "begin"
n_if:         .asciiz "if"
n_cond:       .asciiz "cond"
n_case:       .asciiz "case"
n_quote:      .asciiz "quote"

special_end:  .byte   0

primitive_forms:
op_plus:       .asciiz "+"
op_minus:      .asciiz "-"
op_multiply:   .asciiz "*"
op_divide:     .asciiz "/"
op_mod:        .asciiz "%"


################################################################################
.text

.globl main

################################################################################
# main()
# entry point, read eval and write
################################################################################


main:
    # initialize the heap and swap pointers
    # set aside a single nil value at the beginning of the heap and swap
    la $t0, heap
    la $t1, memory.hp
    sw $t0, 0($t1)
    la $t0, swap
    la $t1, memory.wp
    sw $t0, 0($t1)
	
	# todo ds,es ...
   
    # save the original stack position so the stack can be munged on an exception
	la $sp, stack
    la $t0, memory.sp
    sw $sp, 0($t0)
   
main.loop:
    la $a0, memory.cs  # give the starting position in the input buffer
    jal read_list
    nop
    move $a0, $v1
    la $a1, TOP_ENV
    jal eval
    nop

    move $a0, $v0
    jal write
    nop
    
    j main.loop     #########exit when read_list end
    nop
    j exit
    nop
	
	
	
	
################################################################################
# (char*, object*) read_list(char*)
# Read list into the data/text segment
################################################################################
read_list:
	
    # todo push stack ...

	jal eat_whitespace
    nop
	
	li $t1, '('
    bne $t0, $t1, error.read_list
	
	addi $a0, $a0, 1
	jal read_pair
    nop
	
	# todo pop stack ...


################################################################################
# (char*, object*) read_pair(char*)
# Read pair into the data/text segment
################################################################################
read_pair:

    # todo push stack ...

    jal eat_whitespace
    nop
	
	addi $a0, $a0, 1

	li $t1, ')'
    beq $t0, $t1, read_pair.store_nil
	
	addi $a0, $a0, -1
	jal read
    nop
	
	move $a1, $v0     #car_obj
	
	jal eat_whitespace
    nop
	
	addi $a0, $a0, 1
	li $t1, '.'
	bne $t0, $t1, read_pair.read_dot_else

read_pair.read_dot:
	li $t1, ' '
	beq $t0, $t1, read_pair.read_dot_normal
	li $t1, ')'
	beq $t0, $t1, read_pair.read_dot_normal
	li $t1, '('
	beq $t0, $t1, read_pair.read_dot_normal
	li $t1, '"'
	beq $t0, $t1, read_pair.read_dot_normal
	li $t1, ';'
	beq $t0, $t1, read_pair.read_dot_normal
	li $t1, -1
	beq $t0, $t1, error.read_pair
	
read_pair.read_dot_normal:
	addi $a0, $a0, -1
	jal read
    nop
	
	move $a2, $v1     #cdr_obj
	
	jal eat_whitespace
    nop

	addi $a0, $a0, 1
	li $t1, ')'
	bne $t0, $t1, error.read_pair
	j read_pair.store_cons

read_pair.read_dot_else:
	addi $a0, $a0, -1
	jal read_pair
    nop
	
	j read_pair.store_cons
	
read_pair.store_nil:
	la $t1, memory.ds
    sw $v1, 0($t1)
	b read_pair.exit

read_pair.store_cons:
	la $t1, memory.ds
    sw $v1, 0($t1)
	sw $v2, 0($t1)
	b read_pair.exit
	
read_pair.exit:
	
	# todo pop stack ...
	

################################################################################
# (char*, object*) read(char*)
# Read list into the data/text segment
################################################################################
read:

	# todo 

